home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_055 / csh / sub.c < prev   
C/C++ Source or Header  |  1992-05-06  |  11KB  |  505 lines

  1.  
  2. /*
  3.  * SUB.C
  4.  *
  5.  * (c)1986 Matthew Dillon     9 October 1986
  6.  *
  7.  * version 2.05M (Manx Version and Additions) by Steve Drew 20-Jan-87
  8.  *
  9.  */
  10.  
  11. #include "shell.h"
  12.  
  13. #define HM_STR 0              /* various HISTORY retrieval modes */
  14. #define HM_REL 1
  15. #define HM_ABS 2
  16.  
  17. extern struct FileLock *Clock;
  18. seterr()
  19. {
  20.    char buf[32];
  21.    int stat;
  22.  
  23.    sprintf(buf, "%d", Lastresult);
  24.    set_var(LEVEL_SET, V_LASTERR, buf);
  25.    stat = atoi(get_var(LEVEL_SET, V_STAT));
  26.    if (stat < Lastresult)
  27.       stat = Lastresult;
  28.    sprintf(buf, "%d", stat);
  29.    set_var(LEVEL_SET, V_STAT, buf);
  30. }
  31.  
  32.  
  33. char *
  34. next_word(str)
  35. register char *str;
  36. {
  37.    while (*str  &&  *str != ' '  &&  *str != 9)
  38.       ++str;
  39.    while (*str  && (*str == ' ' || *str == 9))
  40.       ++str;
  41.    return (str);
  42. }
  43.  
  44.  
  45. char *
  46. compile_av(av, start, end)
  47. char **av;
  48. {
  49.    char *cstr;
  50.    int i, len;
  51.  
  52.    len = 0;
  53.    for (i = start; i < end; ++i)
  54.       len += strlen(av[i]) + 1;
  55.    cstr = malloc(len + 1);
  56.    *cstr = '\0';
  57.    for (i = start; i < end; ++i) {
  58.       strcat (cstr, av[i]);
  59.       strcat (cstr, " ");
  60.    }
  61.    return (cstr);
  62. }
  63.  
  64. /*
  65.  * FREE(ptr)   --frees without actually freeing, so the data is still good
  66.  *               immediately after the free.
  67.  */
  68.  
  69.  
  70. Free(ptr)
  71. char *ptr;
  72. {
  73.    static char *old_ptr;
  74.  
  75.    if (old_ptr)
  76.       free (old_ptr);
  77.    old_ptr = ptr;
  78. }
  79.  
  80. /*
  81.  * Add new string to history (H_head, H_tail, H_len,
  82.  *  S_histlen
  83.  */
  84.  
  85. add_history(str)
  86. char *str;
  87. {
  88.    register struct HIST *hist;
  89.  
  90.    if (H_head != NULL && strcmp(H_head->line, str) == 0)
  91.        return(0);
  92.    while (H_len > S_histlen)
  93.       del_history();
  94.    hist = (struct HIST *)malloc (sizeof(struct HIST));
  95.    if (H_head == NULL) {
  96.       H_head = H_tail = hist;
  97.       hist->next = NULL;
  98.    } else {
  99.       hist->next = H_head;
  100.       H_head->prev = hist;
  101.       H_head = hist;
  102.    }
  103.    hist->prev = NULL;
  104.    hist->line = malloc (strlen(str) + 1);
  105.    strcpy (hist->line, str);
  106.    ++H_len;
  107. }
  108.  
  109. del_history()
  110. {
  111.    if (H_tail) {
  112.       --H_len;
  113.       ++H_tail_base;
  114.       free (H_tail->line);
  115.       if (H_tail->prev) {
  116.          H_tail = H_tail->prev;
  117.          free (H_tail->next);
  118.          H_tail->next = NULL;
  119.       } else {
  120.          free (H_tail);
  121.          H_tail = H_head = NULL;
  122.       }
  123.    }
  124. }
  125.  
  126. char *
  127. get_history(ptr)
  128. char *ptr;
  129. {
  130.    register struct HIST *hist;
  131.    register int len;
  132.    int mode = HM_REL;
  133.    int num  = 1;
  134.    char *str;
  135.    char *result = NULL;
  136.  
  137.    if (ptr[1] >= '0' && ptr[1] <= '9') {
  138.       mode = HM_ABS;
  139.       num  = atoi(&ptr[1]);
  140.       goto skip;
  141.    }
  142.    switch (ptr[1]) {
  143.    case '!':
  144.       break;
  145.    case '-':
  146.       num += atoi(&ptr[2]);
  147.       break;
  148.    default:
  149.       mode = HM_STR;
  150.       str  = ptr + 1;
  151.       break;
  152.    }
  153. skip:
  154.    switch (mode) {
  155.    case HM_STR:
  156.       len = strlen(str);
  157.       for (hist = H_head; hist; hist = hist->next) {
  158.          if (strncmp(hist->line, str, len) == 0 && *hist->line != '!') {
  159.             result = hist->line;
  160.             break;
  161.          }
  162.       }
  163.       break;
  164.    case HM_REL:
  165.       for (hist = H_head; hist && num--; hist = hist->next);
  166.       if (hist)
  167.          result = hist->line;
  168.       break;
  169.    case HM_ABS:
  170.       len = H_tail_base;
  171.       for (hist = H_tail; hist && len != num; hist = hist->prev, ++len);
  172.       if (hist)
  173.          result = hist->line;
  174.       break;
  175.    }
  176.    if (result) {
  177.       fprintf(stderr,"%s\n",result);
  178.       return(result);
  179.    }
  180.    printf("History failed\n");
  181.    return ("");
  182. }
  183.  
  184. replace_head(str)
  185. char *str;
  186. {
  187.    if (str == NULL)
  188.       str = "";
  189.    if (H_head) {
  190.       free (H_head->line);
  191.       H_head->line = malloc (strlen(str)+1);
  192.       strcpy (H_head->line, str);
  193.    }
  194. }
  195.  
  196.  
  197. pError(str)
  198. char *str;
  199. {
  200.    int ierr = (long)IoErr();
  201.    ierror(str, ierr);
  202. }
  203.  
  204. ierror(str, err)
  205. register char *str;
  206. {
  207.    register struct PERROR *per = Perror;
  208.  
  209.    if (err) {
  210.       for (; per->errstr; ++per) {
  211.          if (per->errnum == err) {
  212.             fprintf (stderr, "%s%s%s\n",
  213.                   per->errstr,
  214.                   (str) ? ": " : "",
  215.                   (str) ? str : "");
  216.             return ((short)err);
  217.          }
  218.       }
  219.       fprintf (stderr, "Unknown DOS error %ld %s\n", err, (str) ? str : "");
  220.    }
  221.    return ((short)err);
  222. }
  223.  
  224. /*
  225.  * Disk directory routines
  226.  *
  227.  * dptr = dopen(name, stat)
  228.  *    struct DPTR *dptr;
  229.  *    char *name;
  230.  *    int *stat;
  231.  *
  232.  * dnext(dptr, name, stat)
  233.  *    struct DPTR *dptr;
  234.  *    char **name;
  235.  *    int  *stat;
  236.  *
  237.  * dclose(dptr)                  -may be called with NULL without harm
  238.  *
  239.  * dopen() returns a struct DPTR, or NULL if the given file does not
  240.  * exist.  stat will be set to 1 if the file is a directory.  If the
  241.  * name is "", then the current directory is openned.
  242.  *
  243.  * dnext() returns 1 until there are no more entries.  The **name and
  244.  * *stat are set.  *stat = 1 if the file is a directory.
  245.  *
  246.  * dclose() closes a directory channel.
  247.  *
  248.  */
  249.  
  250. struct DPTR *
  251. dopen(name, stat)
  252. char *name;
  253. int *stat;
  254. {
  255.    struct DPTR *dp;
  256.  
  257.    *stat = 0;
  258.    dp = (struct DPTR *)malloc(sizeof(struct DPTR));
  259.    if (*name == '\0')
  260.       dp->lock = (struct FileLock *)DupLock (Clock);
  261.    else
  262.       dp->lock = (struct FileLock *)Lock (name, ACCESS_READ);
  263.    if (dp->lock == NULL) {
  264.       free (dp);
  265.       return (NULL);
  266.    }
  267.    dp->fib = (struct FileInfoBlock *)
  268.          AllocMem((long)sizeof(struct FileInfoBlock), MEMF_PUBLIC);
  269.    if (!Examine (dp->lock, dp->fib)) {
  270.       pError (name);
  271.       dclose (dp);
  272.       return (NULL);
  273.    }
  274.    if (dp->fib->fib_DirEntryType >= 0)
  275.       *stat = 1;
  276.    return (dp);
  277. }
  278.  
  279. dnext(dp, pname, stat)
  280. struct DPTR *dp;
  281. char **pname;
  282. int *stat;
  283. {
  284.    if (dp == NULL)
  285.       return (0);
  286.    if (ExNext (dp->lock, dp->fib)) {
  287.       *stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
  288.       *pname = dp->fib->fib_FileName;
  289.       return (1);
  290.    }
  291.    return (0);
  292. }
  293.  
  294.  
  295. dclose(dp)
  296. struct DPTR *dp;
  297. {
  298.    if (dp == NULL)
  299.       return (1);
  300.    if (dp->fib)
  301.       FreeMem (dp->fib,(long)sizeof(*dp->fib));
  302.    if (dp->lock)
  303.       UnLock (dp->lock);
  304.    free (dp);
  305.    return (1);
  306. }
  307.  
  308.  
  309. isdir(file)
  310. char *file;
  311. {
  312.    register struct DPTR *dp;
  313.    int stat;
  314.  
  315.    stat = 0;
  316.    if (dp = dopen (file, &stat))
  317.       dclose(dp);
  318.    return (stat == 1);
  319. }
  320.  
  321.  
  322. free_expand(av)
  323. register char **av;
  324. {
  325.    char **base = av;
  326.  
  327.    if (av) {
  328.       while (*av) {
  329.          free (*av);
  330.          ++av;
  331.       }
  332.       free (base);
  333.    }
  334. }
  335.  
  336. /*
  337.  * EXPAND(wild_name, pac)
  338.  *    wild_name      - char * (example: "df0:*.c")
  339.  *    pac            - int  *  will be set to # of arguments.
  340.  *
  341.  * Standalone, except in requires Clock to point to the Current-Directory
  342.  * lock.
  343.  */
  344.  
  345.  
  346. char **
  347. expand(base, pac)
  348. char *base;
  349. int *pac;
  350. {
  351.    register char *ptr;
  352.    char **eav = (char **)malloc (sizeof(char *));
  353.    short eleft, eac;
  354.    char *name;
  355.    char *bname, *ename, *tail;
  356.    int stat, scr;
  357.    register struct DPTR *dp;
  358.  
  359.    *pac = eleft = eac = 0;
  360.  
  361.    base = strcpy(malloc(strlen(base)+1), base);
  362.    for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
  363.    for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
  364.    if (ptr < base) {
  365.       bname = strcpy (malloc(1), "");
  366.    } else {
  367.       scr = ptr[1];
  368.       ptr[1] = '\0';
  369.       bname = strcpy (malloc(strlen(base)+1), base);
  370.       ptr[1] = scr;
  371.    }
  372.    ename = ptr + 1;
  373.    for (ptr = ename; *ptr && *ptr != '/'; ++ptr);
  374.    scr = *ptr;
  375.    *ptr = '\0';
  376.    tail = (scr) ? ptr + 1 : NULL;
  377.  
  378.    if ((dp = dopen (bname, &stat)) == NULL  ||  stat == 0) {
  379.       free (bname);
  380.       free (base);
  381.       free (eav);
  382.       fprintf(stderr,"Could not open directory\n");
  383.       return (NULL);
  384.    }
  385.    while (dnext (dp, &name, &stat)) {
  386.       if (compare_ok(ename, name)) {
  387.          if (tail) {
  388.             int alt_ac;
  389.             char *search, **alt_av, **scrav;
  390.             struct FileLock *lock;
  391.  
  392.             if (!stat)           /* expect more dirs, but this not a dir */
  393.                continue;
  394.             lock = (struct FileLock *)CurrentDir (Clock = dp->lock);
  395.             search = malloc(strlen(name)+strlen(tail)+2);
  396.             strcpy (search, name);
  397.             strcat (search, "/");
  398.             strcat (search, tail);
  399.             scrav = alt_av = expand (search, &alt_ac);
  400.             CurrentDir (Clock = lock);
  401.             if (scrav) {
  402.                while (*scrav) {
  403.                   if (eleft < 2) {
  404.                      char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
  405.                      bmov (eav, scrav, (eac + 1) << 2);
  406.                      free (eav);
  407.                      eav = scrav;
  408.                      eleft = 10;
  409.                   }
  410.                   eav[eac] = malloc(strlen(bname)+strlen(*scrav)+1);
  411.                   strcpy(eav[eac], bname);
  412.                   strcat(eav[eac], *scrav);
  413.                   free (*scrav);
  414.                   ++scrav;
  415.                   --eleft, ++eac;
  416.                }
  417.                free (alt_av);
  418.             }
  419.          } else {
  420.             if (eleft < 2) {
  421.                char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
  422.                bmov (eav, scrav, (eac + 1) << 2);
  423.                free (eav);
  424.                eav = scrav;
  425.                eleft = 10;
  426.             }
  427.             eav[eac] = malloc (strlen(bname)+strlen(name)+1);
  428.             eav[eac] = strcpy(eav[eac], bname);
  429.             strcat(eav[eac], name);
  430.             --eleft, ++eac;
  431.          }
  432.       }
  433.    }
  434.    dclose (dp);
  435.    *pac = eac;
  436.    eav[eac] = NULL;
  437.    free (bname);
  438.    free (base);
  439.    if (eac) {
  440.       return (eav);
  441.    }
  442.    free (eav);
  443.    return (NULL);
  444. }
  445.  
  446. /*
  447.  * Compare a wild card name with a normal name
  448.  */
  449.  
  450. #define MAXB   8
  451.  
  452. compare_ok(wild, name)
  453. char *wild, *name;
  454. {
  455.    register char *w = wild;
  456.    register char *n = name;
  457.    char *back[MAXB][2];
  458.    register char s1, s2;
  459.    int  bi = 0;
  460.  
  461.    while (*n || *w) {
  462.       switch (*w) {
  463.       case '*':
  464.          if (bi == MAXB) {
  465.             printf(stderr,"Too many levels of '*'\n");
  466.             return (0);
  467.          }
  468.          back[bi][0] = w;
  469.          back[bi][1] = n;
  470.          ++bi;
  471.          ++w;
  472.          continue;
  473. goback:
  474.          --bi;
  475.          while (bi >= 0 && *back[bi][1] == '\0')
  476.             --bi;
  477.          if (bi < 0)
  478.             return (0);
  479.          w = back[bi][0] + 1;
  480.          n = ++back[bi][1];
  481.          ++bi;
  482.          continue;
  483.       case '?':
  484.          if (!*n) {
  485.             if (bi)
  486.                goto goback;
  487.             return (0);
  488.          }
  489.          break;
  490.       default:
  491.          s1 = (*n >= 'A' && *n <= 'Z') ? *n - 'A' + 'a' : *n;
  492.          s2 = (*w >= 'A' && *w <= 'Z') ? *w - 'A' + 'a' : *w;
  493.          if (s1 != s2) {
  494.             if (bi)
  495.                goto goback;
  496.             return (0);
  497.          }
  498.          break;
  499.       }
  500.       if (*n)  ++n;
  501.       if (*w)  ++w;
  502.    }
  503.    return (1);
  504. }
  505.